/* Copyright 2024 coremail
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *     http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

import { XmlNamespace } from './xml_namespace';
import xml from '@ohos.xml';

export class SoapXmlWriter {
  private static readonly BUFFER_SIZE: number = 4096;

  private arrayBuffer: ArrayBuffer;
  private xmlInstance: xml.XmlSerializer;
  private depth: number = 0;

  constructor() {
    this.arrayBuffer = new ArrayBuffer(SoapXmlWriter.BUFFER_SIZE);
    this.xmlInstance = new xml.XmlSerializer(this.arrayBuffer);
  }

  /**
   * 写入<?xml version="1.0" encoding="utf-8"?>
   *
   * @returns SoapXmlWriter
   */
  public writeStartDocument(): SoapXmlWriter {
    this.xmlInstance.setDeclaration();
    return this;
  }

  public writeElementWithAttribute(namespace: XmlNamespace, elementName: string, attr: Map<string, string>): SoapXmlWriter {
    this.writeStartElement(namespace, elementName);
    if (attr?.size) {
      for (const item of attr) {
        this.writeAttribute(item[0], item[1]);
      }
    }
    this.writeEndElement();
    return this;
  }

  public writeElementWithValue(namespace: XmlNamespace, elementName: string, value: string): SoapXmlWriter {
    return this.writeStartElement(namespace, elementName).writeElementValue(value).writeEndElement();
  }

  public writeIntactElement(namespace: XmlNamespace, elementName: string, attr: Map<string, string>, value: string): SoapXmlWriter {
    this.writeStartElement(namespace, elementName);
    if (attr?.size) {
      for (const item of attr) {
        this.writeAttribute(item[0], item[1]);
      }
    }
    this.writeElementValue(value);
    this.writeEndElement();
    return this;
  }

  /**
   * 写入开始标签 <name>
   *
   * @param name 标签名称
   * @returns SoapXmlWriter
   */
  public writeStartElement(namespace: XmlNamespace, elementName: string): SoapXmlWriter {
    this.xmlInstance.startElement(namespace + ':' + elementName);
    this.depth++;
    return this;
  }

  /**
   * 写入结束标签 </name>
   *
   * @returns SoapXmlWriter
   */
  public writeEndElement(): SoapXmlWriter {
    this.xmlInstance.endElement();
    this.depth--;
    return this;
  }

  public writeAttribute(attributeName: string, value: string): SoapXmlWriter {
    this.xmlInstance.setAttributes(attributeName, value);
    return this;
  }

  public writeAttrWithNamespace(namespace: XmlNamespace, attributeName: string, value: string): SoapXmlWriter {
    this.xmlInstance.setAttributes(namespace + ':' + attributeName, value);
    return this;
  }

  /**
   * 设置文本 <tag>text</tag>
   *
   * @param value 文本值
   * @returns SoapXmlWriter
   */
  public writeElementValue(value: string): SoapXmlWriter {
    this.xmlInstance.setText(value);
    return this;
  }

  /**
   * 获取xml字符串
   *
   * @returns xml字符串
   */
  public getXML(): string {
    let returnVal = '';
    if (this.depth) {
      return returnVal;
    }
    const views = new Uint8Array(this.arrayBuffer);
    for (const view of views) {
      returnVal += String.fromCodePoint(view);
    }
    return returnVal;
  }
}

export class SoapXmlReader {
}